import { Link, RepoLink } from '@brillout/docpress'

In principle, you can use Vike with any authentication tool such as:
- [Better Auth](https://github.com/better-auth/better-auth)
- <Link text="Auth.js" href="/Auth.js" />
- [Grant](https://github.com/simov/grant)
- [Passport.js](https://github.com/jaredhanson/passport)
- [Auth0](https://auth0.com/)
- ...


## `pageContext.user`

You can make information about the authenticated user available to your UI components and Vike hooks by defining a <Link href="/pageContext#custom">custom property</Link> `pageContext.user` in <Link href="/onCreatePageContext">`+onCreatePageContext.server.js`</Link>.

```ts
// pages/+onCreatePageContext.server.ts
// Environment: server

import type { PageContextServer } from 'vike/types'

// This hook is called upon new incoming HTTP requests
export async function onCreatePageContext(pageContext: PageContextServer) {
  // vike-photon exposes the request object at pageContext.runtime.req
  const { req } = pageContext.runtime

  // Authentication middlewares (e.g. Passport.js and Grant) usually set req.user
  // to expose information about the logged-in user.
  const { user } = req
  // Or, when using a third-party authentication provider (e.g. Auth0):
  // @detype-uncomment const user = await someAuthApi.getUser(req.headers)

  // Select the properties you want to make available everywhere
  pageContext.user = {
    firstName: user.firstName,
    email: user.email
  }
}

declare global {
  namespace Vike {
    // We extend PageContext instead of PageContextServer because user is passed to the client
    interface PageContext {
      user?: {
        firstName: string
        email: string
      }
    }
    interface Photon {
      // Pick your server (for correct pageContext.runtime type)
      server: 'hono' // | 'express' | 'fastify' | 'hattip' | 'srvx' | 'elysia' | 'h3'
    }
  }
}
```

```ts
// pages/+config.ts

import type { Config } from 'vike/types'

export default {
  // Make pageContext.user available on the client-side
  passToClient: ['user']
} satisfies Config
```

> See also: <Link href="/passToClient" />

> You can access `pageContext` in any UI component and Vike hook — see <Link href="/pageContext" />.

> If you use <Link href="/vike-photon">`vike-photon`</Link>, you can access the request object at <Link href="/vike-photon#pagecontext-runtime">`pageContext.runtime.req`</Link>.
>
> If you don't use `vike-photon`, you can define a custom property `pageContext.req` at <Link href="/renderPage">`renderPage()`</Link>:
> ```ts
> // server/index.ts
>
> import { renderPage } from 'vike/server'
>
> // Vike server middleware
> app.get('*', async (req: Request, res: Response) => {
>   const pageContextInit = {
>     urlOriginal: req.url,
>     // Make the request object available at pageContext.req
>     req
>   }
>   const pageContext = await renderPage(pageContextInit)
>   // ...
> })
>
> declare global {
>   namespace Vike {
>     interface PageContextServer {
>       req: Request
>     }
>   }
> }
> ```


## SSG

<Link href="/pre-rendering">SSG apps</Link> don't have a server and, therefore, a custom property such as `pageContext.user` cannot be defined on the server-side.

Instead, you can use <Link href="/onCreateGlobalContext">`+onCreateGlobalContext.client.js`</Link>:

```ts
// pages/+onCreateGlobalContext.client.ts
// Environment: client

import type { GlobalContextClient } from 'vike/types'

export async function onCreateGlobalContext(globalContext: GlobalContextClient) {
  // Fetch user information from your backend (or an authentication SaaS platform)
  const user = await fetchUseInfo()
  globalContext.user = user
}
```

You can then use <Link href="/pageContext#globalContext">`pageContext.globalContext`</Link> and/or <Link href="/getGlobalContext">`getGlobalContext()`</Link> to access `globalContext.user` anywhere.



## Login flow

By using <Link href="/guard">+guard</Link> with [`throw redirect()`](/redirect) or [`throw render()`](/render) you can:
 - Implement login flows.
 - Protect private pages from unprivileged access.

```ts
// /pages/admin/+guard.ts

import type { PageContextServer } from 'vike/types'
import { render, redirect } from 'vike/abort'

export const guard = (pageContext: PageContextServer) => {
  const { user } = pageContext
  if (user === null) {
    // Render the login page while preserving the URL. (This is novel technique
    // which we explain down below.)
    throw render('/login')
    /* The more traditional way, redirect the user:
    throw redirect('/login')
    */
  }
  if (user.role !== 'admin') {
    // Render the error page and show message to the user
    throw render(403, 'Only admins are allowed to access this page.')
  }
}
```

> Using `render('/login')` instead of `redirect('/login')` allows the URL to be preserved during the entire login flow:
>  1. Unauthenticated user goes to URL `/admin` and sees the login page. (URL is `/admin`.)
>  2. User fills the sign-in form and successfully logs in. (URL is still `/admin`.)
>  3. <Link text="Reload" href="/reload" /> the page, the user now sees the admin page. (URL is still `/admin`.)
>
> See <RepoLink text="example" path="/examples/auth/" />.

You can also define a `guard()` hook that applies to multiple pages:

```ts
// /pages/+guard.ts

// This guard() hook applies to all pages: the file is located at /pages/+guard.ts
// and therefore applies to all /pages/**/+Page.ts

import type { PageContextServer } from 'vike/types'
import { render } from 'vike/abort'

export const guard = (pageContext: PageContextServer) => {
  if (!pageContext.user) {
    throw render('/login')
  }
}
```

## See also

- <Link href="/guard" />
- <Link href="/redirect" />
- <Link href="/render" />
